package models;

import controllers.AdminUsers;
import helpers.Utils;
import java.io.Serializable;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Types;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;

import javax.xml.bind.annotation.XmlRootElement;
/**
 *
 * @author Rasztemberg
 */
//@Entity
@XmlRootElement
public class User implements Serializable  {
    
    private transient static Logger logger = LogManager.getLogger(AdminUsers.class.getName());
    
    private Integer id;
    private String name;
    private String lastName;
    private String email;
    private String password;
    private String gender;
    private Date dateOfBirth;
    private Date registrationDate;
    private String photo;   
    private Integer active;
    private Integer ip;
    
    public final static String TABLE_NAME = "users";
    public final static String ID_FIELD_NAME = "id";
    public final static String NAME_FIELD_NAME = "name";
    public final static String LNAME_FIELD_NAME = "last_name";
    public final static String EMAIL_FIELD_NAME = "email";
    public final static String PASSWORD_FIELD_NAME = "password";
    public final static String DATE_OF_BIRTH = "date_of_birth";
    public final static String GENDER_FIELD_NAME = "gender";
    public final static String REGDATE_FIELD_NAME = "registered";
    public final static String ACTIVE_FIELD_NAME = "active";
    public final static String PHOTO_FIELD_NAME = "photo";
    
    
    public User(){
    }
    
    private User(Integer id, String name, String lastName, String email, String password, String gender, java.sql.Date registrationDate, Integer active, String photo) {
        this.id = id;
        this.name = name;
        this.lastName = lastName;
        this.email = email;
        this.password = password;
        this.gender = gender;
        //this.registrationDate = registrationDate;
        //this.active = active;
        this.photo = photo;
    }
     //-- DATABASE QUERIES -------------------------------------------------------------------
    
    public int insert(){
        
      
        Connection conn = null;
        int res = -1;
        try{
            conn = Utils.getConnection();
            java.sql.Date regdate = new java.sql.Date(System.currentTimeMillis());
            StringBuilder query = new StringBuilder("INSERT INTO users (");

            query.append(NAME_FIELD_NAME);
            query.append(", ");//1
            query.append(LNAME_FIELD_NAME);
            query.append(", ");//2
            query.append(EMAIL_FIELD_NAME);
            query.append(", ");//3
            query.append(ACTIVE_FIELD_NAME);
            query.append(", ");//4
            query.append(PHOTO_FIELD_NAME);
            query.append(", ");//5
            query.append(PASSWORD_FIELD_NAME);
            query.append(", ");//6
            query.append(REGDATE_FIELD_NAME);
            query.append(", ");//7
            query.append(GENDER_FIELD_NAME);//8 
            query.append(") VALUES (?,?,?,?,?,?,?,?)");//8 params

            PreparedStatement ps =
                    conn.prepareStatement(query.toString(), Statement.RETURN_GENERATED_KEYS);

            ps.setString(1, name);
            ps.setString(2, lastName);
            ps.setString(3, email);
            this.active = 1; // Set
            ps.setInt(4, active);
            ps.setString(5, photo);
            ps.setString(6, password);
            ps.setDate(7, regdate);
            ps.setString(8, gender);
            
            res = ps.executeUpdate();
            ResultSet rs = ps.getGeneratedKeys();
            
            
            if (res >= 1) {
                //get the ID of the new inserted user
                if (rs.next()) {
                    this.id = rs.getInt(1);
               }
            }
            rs.close();
        }catch(SQLException ex){
            logger.error("Exception when creating new user "+name, ex);            
        }finally{
            try {
                if (conn != null && !conn.isClosed()){
                    conn.close();
                }
            } catch (SQLException ex) {
                logger.error("Error closing connection in User class", ex);
            }            
        }            
        return res;
    }
    
    /**
     * Select a user from DB 
     * @param id - the id of the user from the DB
     * @return a User from the db or <b>null</b> if no user was not found or an exception occurred 
     */
    public static User selectById(Integer id) {
        User user = null;
        Connection conn = null;
        
        try{
            conn = Utils.getConnection();
            String query = "SELECT * FROM " + TABLE_NAME + " WHERE "
                    + "id=? ";
            PreparedStatement ps = conn.prepareStatement(query);
            ps.setInt(1, id);
            ResultSet rs = ps.executeQuery();
            if (!rs.next()) {
                return null;
            }      
            
            String name = rs.getString(NAME_FIELD_NAME);
            String lname = rs.getString(LNAME_FIELD_NAME);
            String email = rs.getString(EMAIL_FIELD_NAME);
            String password = rs.getString(PASSWORD_FIELD_NAME); 
            java.sql.Date regDate = rs.getDate(REGDATE_FIELD_NAME);
            int active = rs.getInt(ACTIVE_FIELD_NAME);
            String photo = rs.getString(PHOTO_FIELD_NAME);
            String gender = rs.getString(GENDER_FIELD_NAME);
           
            user = new User();
            user.setId(id);
            user.setName(name);
            user.setLastName(lname);
            user.setEmail(email);
            user.setPassword(password);
            user.setRegistrationDate(regDate);
            user.setActive(active);
            user.setPhoto(photo);
            user.setGender(gender);
            
            rs.close();
            
        }catch(SQLException ex){
            logger.error("Exception when getting User "+ id, ex);
        }finally{
            try {
                if (conn!=null && !conn.isClosed())
                    conn.close();
            } catch (SQLException ex) {
                logger.error("Error closing connection in User class", ex);
            }           
        }
        return user;
    }
    
  
   public int update() {
       
        int res = -1;
        Connection conn = null;
        try{
            conn = Utils.getConnection();
            StringBuilder query = new StringBuilder("UPDATE "+TABLE_NAME+" SET ");

            query.append(NAME_FIELD_NAME);
            query.append("=?, ");//1
            query.append(LNAME_FIELD_NAME);
            query.append("=?, ");//2
            query.append(EMAIL_FIELD_NAME);
            query.append("=?, ");//3
            query.append(ACTIVE_FIELD_NAME);
            query.append("=?, ");//4
            query.append(PHOTO_FIELD_NAME);
            query.append("=?, ");//5
            query.append(GENDER_FIELD_NAME);
            query.append("=? ");//6
            query.append(" WHERE id = ?");//7        
            PreparedStatement ps = conn.prepareStatement(query.toString());
            //remeber to change number of parameter if you change anything
            ps.setString(1, getName());
            ps.setString(2, getLastName());
            ps.setString(3, getEmail());
            ps.setInt(4, getActive());
            ps.setString(5, getPhoto());
            if (gender==null) 
                ps.setNull(6, Types.CHAR);
            else    
                ps.setString(6, gender);  
            ps.setInt(7, getId());

            res = ps.executeUpdate();          
        }catch(SQLException ex){
            logger.error("Exception when updating User "+ id, ex);
        }finally{
            try {
                if (conn!=null  && !conn.isClosed()){
                    conn.close();
                }
            } catch (SQLException ex) {
                logger.error("Error closing connection in User class", ex);
            }           
        }
        return res;
    }
    
    /**
     * deletes a user from the DB based on ID     * 
     * @return true if update successful false otherwise
     * 
     */
    public int delete(){
        int res = -1;
        Connection conn = null;
        
        try{
            conn = Utils.getConnection();
            String query = "DELETE FROM users where id = ?";
            PreparedStatement ps =
                    conn.prepareStatement(query);
            ps.setInt(1, id);
            res = ps.executeUpdate();
            
        }catch(SQLException ex){
            logger.error("Exception when updating User "+ id, ex);
        }finally{
            try {
                if(conn!=null && !conn.isClosed())
                    conn.close();
            } catch (SQLException ex) {
             //   logger.error("Error closing connection in User class", ex);
            }           
        }
        return res;
    }
    /*
     * Searches for users in DB by search term: name (it will search through 
     * last names as well) 
     * @param name name search term
     * @return An List of User or <b>null</b> if an exception occurred 
     */
    public static List<User> getUsersByName(String name,
            int initialIndex,
            int number) {
        List<User> list = null;
        Connection conn = null;
        try{
            conn = Utils.getConnection();
            StringBuilder query = new StringBuilder("SELECT * FROM ");
            query.append(TABLE_NAME);
            query.append(" WHERE ");
            query.append(NAME_FIELD_NAME);
            query.append(" LIKE ? OR ");
            query.append(LNAME_FIELD_NAME);
            query.append(" LIKE ? ");
            query.append(" ORDER BY id " );
            query.append(" LIMIT ?, ?");
            PreparedStatement ps =
                    conn.prepareStatement(query.toString());
            ps.setString(1, "%"+name+"%");
            ps.setString(2, "%"+name+"%");
            ps.setInt(3, initialIndex);
            ps.setInt(4, number);

            list = new ArrayList<User>();
            ResultSet rs = ps.executeQuery();
            while (rs.next()) {       
                User user = new User();
                user.setId(rs.getInt(ID_FIELD_NAME));
                user.setName(rs.getString(NAME_FIELD_NAME));
                user.setLastName(rs.getString(LNAME_FIELD_NAME));
                user.setEmail(rs.getString(EMAIL_FIELD_NAME));
                user.setPassword(rs.getString(PASSWORD_FIELD_NAME));
                user.setRegistrationDate(rs.getDate(REGDATE_FIELD_NAME));
                user.setActive(rs.getInt(ACTIVE_FIELD_NAME));
                user.setPhoto(rs.getString(PHOTO_FIELD_NAME));
                list.add(user);
            }
            rs.close();
            
        }catch(SQLException ex){
            logger.error("Exception when creating new user "+name, ex);
        }finally{
            try {
                if(conn!=null && !conn.isClosed())
                    conn.close();
            } catch (SQLException ex) {
                logger.error("Error closing connection in User class", ex);
            }           
        }
        return list;
    }
    
    public static List<User> selectAllUsers(){
        List<User> list = null;
        Connection conn = null;
        
         try{
            conn = Utils.getConnection();
            StringBuilder query = new StringBuilder("SELECT " + NAME_FIELD_NAME + "," + LNAME_FIELD_NAME  + "," + EMAIL_FIELD_NAME + " FROM ");
            query.append(TABLE_NAME);
            list = new ArrayList<User>();
            PreparedStatement ps = conn.prepareStatement(query.toString());
            ResultSet rs = ps.executeQuery();
            while (rs.next()) {       
                User user = new User();
                 // user.setId(rs.getInt(ID_FIELD_NAME));
                  user.setName(rs.getString(NAME_FIELD_NAME));
                  user.setLastName(rs.getString(LNAME_FIELD_NAME));
                  user.setEmail(rs.getString(EMAIL_FIELD_NAME));
                  user.setPassword("XXXX");
            //  user.setRegistrationDate(rs.getDate(REGDATE_FIELD_NAME));
              //  user.setActive(rs.getInt(ACTIVE_FIELD_NAME));
              //  user.setPhoto(rs.getString(PHOTO_FIELD_NAME));
                list.add(user);
            }
            rs.close();
            
        }catch(SQLException ex){
            logger.error("There was an error in selecting all ussers", ex);
        }finally{
            try {
                if(conn!=null && !conn.isClosed())
                    conn.close();
            } catch (SQLException ex) {
                logger.error("Error closing connection in User class", ex);
            }           
        }
        return list;
        
    }
    
    // SETTERS -----------------------------------------------------------

    public void setId(Integer id) {
        this.id = id;
    }
    
    public void setName(String name) {
        this.name = name;
    }
    
    public void setLastName(String lastName) {
        this.lastName = lastName;
    }
    
    public void setGender(String gender) {
        this.gender = gender;
    }
    
    public void setPassword(String password) {
        this.password = password;
    }
    
    public void setEmail(String email) {
        this.email = email;
    }
    
    public void setDateOfBirth(Date dateOfBirth) {
        this.dateOfBirth = dateOfBirth;
    }
    
    public void setPhoto(String photo) {
        this.photo = photo;
    }
    
    public void setRegistrationDate(Date registrationDate) {
        this.registrationDate = registrationDate;
    }
    
    public void setActive(Integer active) {
        this.active = active;
    }
    
    public void setIp(Integer ip) {
        this.ip = ip;
    }
    
    // GETTERS ----------------------------------------------------------

    public String getName() {
        return name;
    }

    public String getPassword() {
        return password;
    }

    public String getPhoto() {
        return photo;
    }
    
    public Date getRegistrationDate() {
        return registrationDate;
    }
    
    public Date getDateOfBirth() {
        return dateOfBirth;
    }

    public Integer getActive() {
        return active;
    }

    public String getEmail() {
        return email;
    }
    
    public Integer getId() {
        return id;
    }

    public Integer getIp() {
        return ip;
    }
    
    public String getLastName() {
        return lastName;
    }

    public String getGender() {
        return gender;
    }

    // END OF CLASS ----------------------------------------------------
}
